import { Component, OnInit, Host, Input } from '@angular/core';
import { Store } from '@ngrx/store';

import View from 'ol/view';
import Coordinate from 'ol/coordinate';
import Extent from 'ol/extent';

import { ViewState } from '../../store/reducers/view.reducer';
import { ViewUpdate } from '../../store/actions/view.action';

import { MapState, poisSelectors, districtsSelector, zoomSelector, ZoomState } from '../../../map/store';
import { Poi, District, UserLocation } from '../../models';

import { MapComponent } from '../map/map.component';

@Component({
  selector: 'ngx-ol-view',
  templateUrl: './view.component.html',
  styleUrls: ['./view.component.scss']
})
export class ViewComponent implements OnInit {

  public instance: View;

  @Input() center: Coordinate = [0, 0];
  @Input() constrainRotation: boolean|number;
  @Input() enableRotation: boolean;
  @Input() extent: Extent;
  @Input() maxResolution: number;
  @Input() minResolution: number;
  @Input() maxZoom: number;
  @Input() minZoom: number;
  @Input() resolution: number;
  @Input() resolutions: number[];
  @Input() rotation: number;
  @Input() zoom: number = 15;
  @Input() zoomFactor: number;
  @Input() autoLocation: boolean = true;

  constructor(
    private olStore: Store<ViewState>,
    private mapStore: Store<MapState>,
    @Host() protected host: MapComponent
  ) { }

  ngOnInit() {
    this.instance = new View(this);
    this.host.instance.setView(this.instance);
    this.updateStore();
    this.bindEvent();
    this.mapStore.select(poisSelectors.getSelectPois)
      .subscribe((poi: Poi) => {
        if(poi) {
          this.setCenterAndZoom(poi.point, 17);
        }
      });
    this.mapStore.select(districtsSelector.getDistrictSelected)
      .subscribe((district: UserLocation) => {
        if(district) {
          this.setExtentAndZoom(district.extent);
        }
      });
    this.mapStore.select(zoomSelector.getZoomState).subscribe((zoom: ZoomState) => {
      if(zoom.increment) {
        this.zoomControl('Increment');
      }
      if(zoom.decrement) {
        this.zoomControl('Decrement');
      }
    });
  }

  setCenterAndZoom(center: number[], zoom: number): void {
    this.instance.animate({ center, zoom, duration: 300 });
  }

  setExtentAndZoom(extent: number[]) {
    this.instance.fit(extent);
  } 

  bindEvent(): void {
    this.instance.on('change', (e) => {
      this.updateStore();
    });
  }

  updateStore(): void {
    const center: number[] = this.instance.getCenter();
    const zoom: number = Math.round(this.instance.getZoom()*1)/1;
    const minZoom: number = this.instance.getMinZoom();
    const maxZoom: number = this.instance.getMaxZoom();
    const disabledZoomIn: boolean = zoom >= maxZoom ? true : false;
    const disabledZoomOut: boolean = zoom <= minZoom ? true : false;
    this.olStore.dispatch(new ViewUpdate({
      center,
      zoom,
      minZoom,
      maxZoom,
      disabledZoomIn,
      disabledZoomOut
    }));
  }

  zoomControl(mothed: 'Increment' | 'Decrement'): void {
    const center = this.instance.getCenter();
    const currentZoom = this.instance.getZoom();
    const maxZoom = this.instance.getMaxZoom();
    const minZoom = this.instance.getMinZoom();
    let zoom: number;
    switch(mothed) {
      case 'Increment': {
        zoom = currentZoom + 1 > maxZoom ? maxZoom : currentZoom + 1;
        break;
      }
      case 'Decrement': {
        zoom = currentZoom - 1 < minZoom ? minZoom : currentZoom - 1;
        break;
      }
      default: {
        zoom = currentZoom;
        break;
      }
    }
    this.setCenterAndZoom(center, zoom);
  }



}
